﻿// Inner Fire 游戏引擎库
// Constraint - 物理约束
//
// Copyright (c) 2025 by 尔西大帝. All rights reserved.
//
// 所属层级：应用层（4）
// 用于解决碰撞中的穿透问题。
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2025-06-28

#pragma once

#include <DirectXCollision.h>
#include <graphics/graphics_def.h>
#include <graphics/mat_mn.h>

namespace ifire::game {
class RigidBody;

class Constraint {
public:
  RigidBody* a;
  RigidBody* b;

  Constraint();
  virtual ~Constraint() = default;

  MatMN<12, 12> GetInvM() const;
  VecN<12> GetVelocities() const;
  virtual void PreSolve(float dt) = 0;
  virtual void Solve() = 0;
  // 我的ClampVelocities，那些检查都可以用在这个地方！不用每次Impulse都检查。太伤了。
  virtual void PostSolve() = 0;

protected:
  float bias;
  IVec3 aPoint; // The anchor point in A's local space
  IVec3 bPoint; // The anchor point in B's local space
};

class JointConstraint : public Constraint {
public:
  JointConstraint();
  JointConstraint(RigidBody* a, RigidBody* b, IVec3 anchorPoint);
  void PreSolve(float dt) override;
  void Solve() override;
  void PostSolve() override;

private:
  MatMN<1, 12> jacobian;
  VecN<1> cached_lambda;
};

class PenetrationConstraint : public Constraint {
public:
  PenetrationConstraint();
  PenetrationConstraint(RigidBody* a, RigidBody* b, IVec3 a_point,
      IVec3 b_point, IVec3 normal);

  void PreSolve(float dt) override;
  void Solve() override;
  void PostSolve() override;

private:
  MatMN<2, 12> jacobian;
  VecN<2> cached_lambda;

  IVec3 normal;
  IVec va, vb;
  float friction;
  float vrel_dot_n;
};


// TODO，铰链约束，用来实现布娃娃系统。
//class HingeConstraint : public Constraint {
//public:
//  HingeConstraint();
//  HingeConstraint(RigidBody* a, RigidBody* b, IVec3 a_point,
//      IVec3 b_point, IVec3 normal);
//
//  void PreSolve(float dt) override;
//  void Solve() override;
//  void PostSolve() override;
//
//private:
//  MatMN<2, 12> jacobian;
//  VecN<2> cached_lambda;
//
//  IVec3 normal;
//  float friction;
//};

} // namespace ifire::game